#pragma once

#include <metalc/mlayer/_mlayer.h>

#ifndef METALC_DYNLIB
	#ifndef FTEST
	#warning "using LD_PRELOAD may lead to [tsysmalloc] failed with consturctor enabled"  
	#endif
#endif
/* 定义mreq */

#include <malloc.h>
#include <stdlib.h>
#include <dlfcn.h>
static void *(*myfn_calloc)(size_t nmemb, size_t size);
static void *(*myfn_malloc)(size_t size);
static void (*myfn_free)(void *ptr);
static size_t (*myfn_malloc_size)(void *ptr);
static void *(*myfn_realloc)(void *ptr, size_t size);
static void *(*myfn_memalign)(size_t blocksize, size_t bytes);

DEF_MLOS(tsysmalloc, 0)

// static bool_t tsysmalloc_initialized = 0;
static inline void tsysmalloc_pinit(const mlfunc_t *next)
{
	PARAM_USED(next);
	INFO("dlsym start\n");
	myfn_malloc = dlsym(RTLD_NEXT, "malloc");
	// fprintf(stderr, "initialized succ 1\n");
	myfn_free = dlsym(RTLD_NEXT, "free");
	myfn_calloc = dlsym(RTLD_NEXT, "calloc");
	myfn_realloc = dlsym(RTLD_NEXT, "realloc");
	myfn_memalign = dlsym(RTLD_NEXT, "memalign");
	myfn_malloc_size = dlsym(RTLD_NEXT, "malloc_usable_size");
	if (!myfn_malloc || !myfn_free || !myfn_calloc || !myfn_realloc || !myfn_memalign || !myfn_malloc_size)
	{
		fatal("dlsym failed\n");
	}
	// tsysmalloc_initialized = 1;
	INFO("replaced malloc\n");
}

static inline void tsysmalloc_tinit(const mlfunc_t *next)
{
	PARAM_USED(next);
}
/* 初始化流程先procinit -> 不能调用任何可能malloc的接口 -> 初始化必要的内存分配 */

SAI void *tsysmalloc_alloc(mreq_t *req, const mlfunc_t *next)
{
	PARAM_USED(next);
	// if (!tsysmalloc_initialized)apdsnode_alloc();
	// mtls_t *tls = mtls_by_req(req);
	// word_t size = align_up(req->size, sizeof(word_t));
	// fprintf(stderr, "[tsysm]%lu\n", req->size);
	// fprintf(stderr, "%lx\n");
	
	req->ptr = myfn_malloc(req->size);
	// req->size = size;
	return req->ptr;
}

SAI bool_t tsysmalloc_free(mreq_t *req, const mlfunc_t *next)
{
	PARAM_USED(next);
	// fprintf(stderr, "[f]%lu\n", req->size);
	myfn_free(req->ptr);
	return TRUE;
}

SAI size_t tsysmalloc_sizeof(mreq_t *req, const mlfunc_t *next)
{
	PARAM_USED(next);
	req->size = myfn_malloc_size(req->ptr);
	return req->size;
}
